use super::{err, err_value, throw_err, ECode, Value};

pub trait KeyNode {
    fn key_run(&self, model: &str) -> Result<String, Value>;
    fn key_pause(&self, model: &str) -> Result<String, Value>;
    fn key_all(&self, model: &str) -> Result<String, Value>;
    fn key_sn(&self, model: &str, sn: &str) -> Result<String, Value>;
    fn key_sn_ext(&self, model: &str, sn: &str, ext: &str) -> Result<String, Value>;
    fn key_sub_sn(&self, model: &str, sub: &str, sn: &str) -> Result<String, Value>;
    fn key_sub_sn_ext(&self, model: &str, sub: &str, sn: &str, ext: &str) -> Result<String, Value>;

    fn key_value(
        &self,
        line: &str,
        model: &str,
        sub: Option<&str>,
        sn: &str,
        ext: Option<&str>,
    ) -> Result<String, Value> {
        let m = match model {
            "auth" => "a",
            "stell" => "b",
            "buy" => "B",
            "cur" => "c",
            "code" => "d",
            "oil" => "D",
            "tech" => "e",
            "cera" => "f",
            "pick" => "g",
            "sidehand" => "h",
            "lathe" => "i",
            "order" => "j",
            "sideauto" => "k",
            "cage" => "m",
            "seal" => "n",
            "psn" => "p",
            "equip" => "q",
            "back" => "r",
            "part" => "R",
            "station" => "s",
            "task" => "t",
            "sale" => "T",
            "user" => "u",
            "forge" => "v",
            "goods" => "w",
            "away" => "W",
            "money" => "x",
            "inner" => "y",
            "outer" => "z",
            _ => throw_err!(ECode::Collect, "model type error"),
        };

        let s = match sub {
            Some(v) => {
                let tmp = match v {
                    "bom" => "b",
                    "pause" => "c",
                    "day" => "d",
                    "esop" => "e",
                    "all" => "g",
                    "month" => "m",
                    "run" => "n",
                    "psn" => "p",
                    "equip" => "q",
                    "rework" => "r",
                    "user" => "u",
                    "year" => "y",
                    _ => throw_err!(ECode::Collect, "sub type error"),
                };

                Some(tmp)
            }
            None => None,
        };

        let key = match s {
            Some(v) => format!("{line}{m}{v}{sn}"),
            None => format!("{line}{m}_{sn}"),
        };

        let ret = match ext {
            Some(v) => format!("{key}{v}"),
            None => key,
        };

        Ok(ret)
    }
}
